package com.lucky.common.util;

import org.apache.cxf.configuration.jsse.TLSClientParameters;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;
import org.apache.cxf.transport.http.HTTPConduit;
import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.SocketTimeoutException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;

public class CxfClient {
	
	private static final Logger logger = LoggerFactory.getLogger(CxfClient.class);

	public static String callEnterprice(String wsdl, String methodName, String data) throws Exception {
		return CxfClient.callWebService(wsdl, methodName, data);
	}
	
	public static String callBank(String wsdl, String methodName, String data, String file) throws Exception {
		return CxfClient.callWebService(wsdl, methodName, data, file);
	}
	
	public static String callWebService(String wsdl, String methodName, Object... data) throws Exception {
		
		String returnStr = "error";
		try {
			JaxWsDynamicClientFactory clientFactory = JaxWsDynamicClientFactory.newInstance();
			Client client = clientFactory.createClient(wsdl);

			//需要添加超时参数等,添加如下代码
			HTTPConduit conduit = (HTTPConduit) client.getConduit();// 获取静态映射
			HTTPClientPolicy policy = new HTTPClientPolicy();// 创建策略
//			policy.setAllowChunking(false); // 设置允许分块传输
			policy.setConnectionTimeout(60000);// 连接服务器超时时间3分钟
			policy.setReceiveTimeout(60000);// 等待服务器响应超时时间3分钟
			policy.setMaxRetransmits(60000);
			conduit.setClient(policy); // 将策略设置进端点
			conduit.setTlsClientParameters(getTLSClientParameters());  //设置SSL证书

			logger.info("开始调用银行服务端接口");
			Object[] result = client.invoke(methodName, data);
			returnStr = result[0].toString();
			logger.info("返回报文: "+ returnStr);
			logger.info("结束调用银行服务端接口");
		} catch (SocketTimeoutException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}

		return returnStr;
	}
	
	
	/**
	 * @param jksFilePath
	 * @param password
	 * @return
	 * @throws KeyStoreException
	 * @throws NoSuchAlgorithmException
	 * @throws CertificateException
	 * @throws IOException
	 * @throws UnrecoverableKeyException
	 */
	private static TLSClientParameters getTLSClientParameters(String jksFilePath, String password) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, UnrecoverableKeyException{
		
		TLSClientParameters tlsClientParameters = new TLSClientParameters();  
		
		// 密钥类型  
//		KeyStore keyStore = KeyStore.getInstance("pkcs12");//key.p12 
		// // 读取信任仓库  , 加载密钥  
		KeyStore keyStore = KeyStore.getInstance("JKS"); //key.jks
		keyStore.load(new FileInputStream(jksFilePath), password.toCharArray());  
		  
		//set trust keystore  
		// 信任仓库的默认算法X509  
        // 获取信任仓库工厂 
		// 读取信任仓库  
        String trustAlg = TrustManagerFactory.getDefaultAlgorithm();  
		TrustManagerFactory trustFactory = TrustManagerFactory.getInstance(trustAlg);  
		trustFactory.init(keyStore);  
		tlsClientParameters.setTrustManagers(trustFactory.getTrustManagers());   
		  
		//set keystore  
		// 获取默认的 X509算法  
        // 创建密钥管理工厂  
        String kayAlg = KeyManagerFactory.getDefaultAlgorithm();  
		KeyManagerFactory keyFactory = KeyManagerFactory.getInstance(kayAlg);  
		keyFactory.init(keyStore, password.toCharArray());  

//		tlsClientParameters.setSecureSocketProtocol("SSL");  
		tlsClientParameters.setDisableCNCheck(true); 
		tlsClientParameters.setKeyManagers(keyFactory.getKeyManagers());  
		 
		return tlsClientParameters;
	}
	

	/**
	 * @param jksFilePath
	 * @param password
	 * @return
	 * @throws KeyStoreException
	 * @throws NoSuchAlgorithmException
	 * @throws CertificateException
	 * @throws IOException
	 * @throws UnrecoverableKeyException
	 */
	private static TLSClientParameters getTLSClientParameters() throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, UnrecoverableKeyException{
		
		TLSClientParameters tlsClientParameters = new TLSClientParameters();  
		
		X509TrustManager trustManager = new X509TrustManager() {
			@Override
			public void checkClientTrusted(java.security.cert.X509Certificate[] paramArrayOfX509Certificate,
					String paramString) throws CertificateException {
			}

			@Override
			public void checkServerTrusted(java.security.cert.X509Certificate[] paramArrayOfX509Certificate,
					String paramString) throws CertificateException {
			}

			@Override
			public java.security.cert.X509Certificate[] getAcceptedIssuers() {
				return null;
			}
		};
		
		TrustManager[] trustAllCerts = new TrustManager[] {trustManager};
		tlsClientParameters.setTrustManagers(trustAllCerts);

		// disables verification of the common name (the host for which the certificate has been issued)
		tlsClientParameters.setDisableCNCheck( true );
		 
		return tlsClientParameters;
	}
	
}